//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<CBlendState10.cpp>
///	@path	~/src/graphics/dx10/
///	@date	2008/12/22
///	@desc	.


#include "config/config.h"

#include "graphics/RenderContext.h"
#include "graphics/dx10/CBlendState10.h"

namespace xeres {

	IMPL_IOBJECT_CLASS( CBlendState10 );

	namespace
	{
		static inline D3D10_BLEND_OP to_op( BlendOpType op )
		{
			switch( op )
			{
			case BLENDOP_ADD: return D3D10_BLEND_OP_ADD;
			case BLENDOP_SUB: return D3D10_BLEND_OP_SUBTRACT;
			case BLENDOP_RSUB: return D3D10_BLEND_OP_REV_SUBTRACT;
			case BLENDOP_MIN: return D3D10_BLEND_OP_MIN;
			case BLENDOP_MAX: return D3D10_BLEND_OP_MAX;
			}
			XS_ASSERT(false);
			return D3D10_BLEND_OP(0);
		}

		static inline D3D10_BLEND to_type( BlendType type )
		{
			switch( type )
			{
			case BLEND_ZERO: return D3D10_BLEND_ZERO;
			case BLEND_ONE: return D3D10_BLEND_ONE;
			case BLEND_SRCCOLOR: return D3D10_BLEND_SRC_COLOR;
			case BLEND_INVSRCCOLOR: return D3D10_BLEND_INV_SRC_COLOR;
			case BLEND_SRCALPHA: return D3D10_BLEND_SRC_ALPHA;
			case BLEND_INVSRCALPHA: return D3D10_BLEND_INV_SRC_ALPHA;
			case BLEND_DESTALPHA: return D3D10_BLEND_DEST_ALPHA;
			case BLEND_INVDESTALPHA: return D3D10_BLEND_INV_DEST_ALPHA;
			case BLEND_DESTCOLOR: return D3D10_BLEND_DEST_COLOR;
			case BLEND_INVDESTCOLOR: return D3D10_BLEND_INV_DEST_COLOR;
			case BLEND_SRCALPHASAT: return D3D10_BLEND_SRC_ALPHA_SAT;
			case BLEND_BLENDFACTOR: return D3D10_BLEND_BLEND_FACTOR;
			case BLEND_INVBLENDFACTOR: return D3D10_BLEND_INV_BLEND_FACTOR;
			}
			XS_ASSERT(false);
			return D3D10_BLEND(0);
		}
	}
	// CBlendState10
	CBlendState10::CBlendState10( BlendSet& blend_set , RefWeak<CDevice10> device )
		: m_state( NULL )
	{
		D3D10_BLEND_DESC desc;
		memset( &desc , 0 , sizeof(D3D10_BLEND_DESC) );
		desc.AlphaToCoverageEnable = blend_set.alpha_to_coverage;
		for( int i = 0 ; i < 8 ; ++i )
		{
			desc.BlendEnable[i] = blend_set.enable_blend[i];
			desc.RenderTargetWriteMask[i] = blend_set.color_write[i];
		}
		desc.SrcBlend = to_type( blend_set.color_src );
		desc.DestBlend = to_type( blend_set.color_dst );
		desc.BlendOp = to_op( blend_set.color_op );
		desc.SrcBlendAlpha = to_type( blend_set.separate_alpha ? blend_set.alpha_src : blend_set.color_src );
		desc.DestBlendAlpha = to_type( blend_set.separate_alpha ? blend_set.alpha_dst : blend_set.color_dst );
		desc.BlendOpAlpha = to_op( blend_set.separate_alpha ? blend_set.alpha_op : blend_set.color_op );

		HRESULT hr = device->GetDevice()->CreateBlendState( &desc , &m_state );
		XS_ASSERT( SUCCEEDED(hr) );
	}
	// ~CBlendState10
	CBlendState10::~CBlendState10( void )
	{
		if( m_state )
		{
			UINT rest = m_state->Release();
			if( rest != 0 )
			{
				TRACE_ERROR( _S("CBlendState10::DTOR: Invalid ID3D10BlendState reference count.") );
				FATAL_ABORT( _S("Invalid ID3D10BlendState reference count.") );
			}
		}
	}
	// Apply
	void CBlendState10::Apply( RenderContext& rc )
	{
		if( m_state )
		{
			const FLOAT factor[4] = {1,1,1,1};
			rc.GetDX10()->OMSetBlendState( m_state , factor , 0xffffffff );
		}
	}

} // namespace xeres
